package parser;

import java.io.PrintWriter;

import lexer.TokenType;

/**
 * Parses etc a LOGO procedure call Grammar: PROCEDURE(ARGUMENT)
 */
public class LogoProcedureCallStatement extends LogoStatement {

	LogoExpression argument;
	String procedureIdentifier;

	/**
	 * Reads in a Procedure call from the Iterator.
	 * 
	 * @param TokenIterator
	 * @throws LogoParseException
	 */
	public LogoProcedureCallStatement(TokenIterator it) throws LogoParseException {
		parseTokens(it);
	}

	private void parseTokens(TokenIterator it) throws LogoParseException {
		if (!it.hasNext()) {
			throw new LogoParseException("Unexpectedly reached end of program");
		}
		if (!it.matchTokenPattern(TokenType.IDENTIFIER, TokenType.LEFT_BRACKET)) {
			throw new LogoParseSyntaxException(it.next(), "Invalid statement. Attempted to parse as Procedure Call. ");
		}
		procedureIdentifier = it.ExpectedNext(TokenType.IDENTIFIER).getContents();

		it.ExpectedNext(TokenType.LEFT_BRACKET);

		argument = LogoExpressionParser.parseExpression(it);

		it.ExpectedNext(TokenType.RIGHT_BRACKET);
	}

	@Override
	public void resolveIdentifiers(LogoScope scope) throws LogoParseException {
		argument.resolveIdentifiers(scope);

		if (scope.getTypeOf(procedureIdentifier) == LogoIdentifierType.PROCEDURE) {
			return;
		} else if (scope.getTypeOf(procedureIdentifier) == LogoIdentifierType.VARIABLE) {
			throw new LogoParseException("Invalid identifier. Expected " + procedureIdentifier + " to be type PROCEDURE. Actual type VARIABLE");
		} else {
			throw new LogoParseException("Unidentified identifier " + procedureIdentifier);
		}
	}

	/**
	 * Example Output: 11 LDRAGON
	 */
	@Override
	public void generatePostScriptCode(PrintWriter stream) {
		argument.generatePostScriptCode(stream);
		
		stream.println(procedureIdentifier);
		// Get the argument back from the stack after calling the function
		stream.println("/Arg exch def");
	}
}
